#include "media_audio_manager.h"

#include <algorithm>
#include <inttypes.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/time.h>
#include <vector>
#include <cassert>
#include <memory>
#include <utility>
#include "utils_log.h"
#include "common_config_manager.h"
#include "common_event.h"
#include "hal_audio.h"
#include "utils_time.h"

namespace El {
namespace Media {

MediaAudioManager &MediaAudioManager::GetInstance(int32_t ch)
{
    static std::map<int32_t, MediaAudioManager *> g_instances;
    static std::mutex g_mutex;

    std::lock_guard<std::mutex> lock(g_mutex);
    auto it = g_instances.find(ch);
    if (it == g_instances.end()) {
        MediaAudioManager *instance = new MediaAudioManager(ch);
        g_instances.emplace(ch, instance);
        return *instance;
    }
    return *it->second;
}

MediaAudioManager::MediaAudioManager(int32_t ch) : ch_(ch)
{
    EL_INFO("MediaAudioManager ch:{} created", ch_);
}

MediaAudioManager::~MediaAudioManager() {}

int32_t MediaAudioManager::Start(const Proc &proc)
{
    bool audioEnable = true;
    auto config = Common::ConfigManager::GetInstance().GetConfig("/audio_encode/0");
    if (!config.empty()) {
        audioEnable = config["enable"].get<bool>();
    }

    // 开启音频编码
    if (!audioEnable) {
        EL_WARN("audio is not enable");
        return -1;
    }

    std::lock_guard<std::mutex> lock(mutex_);
    if (!start_) {
        // 读取音频输入源配置
        auto audioInputConfig = Common::ConfigManager::GetInstance().GetConfig("/audio_input");
        std::string sourceStr = "usb"; // 默认USB
        if (!audioInputConfig.is_null()) {
            sourceStr = audioInputConfig.value("source", "usb");
        }
        
        currentSource_ = AudioInputSource::BUILTIN;
        usbCardId_.clear();
        // 启动内置音频编码，如果失败则直接返回错误
        if (!StartAudio()) {
            EL_ERROR("Failed to start builtin audio as configured, ch:{}", ch_);
            return -1;
        }

        start_ = true;
        audioThread_ = std::make_unique<std::thread>(&MediaAudioManager::AudioThread, this);
    }

    EL_INFO("start audio encoder ch:{} succeed", ch_);
    return callbackManager_.Register(proc);
}

bool MediaAudioManager::StartAudio()
{
    auto audioConfig = Common::ConfigManager::GetInstance().GetConfig("/audio_encode/" + std::to_string(ch_));
    if (audioConfig.is_null()) {
        EL_ERROR("Failed to get audio config for ch:{}", ch_);
        return false;
    }
    EL_INFO("start audio: ch {} config {}", ch_, audioConfig.dump(4).c_str());

    HAL_AENC_COM_CONFIG_S stAencConfig;
    memset(&stAencConfig, 0, sizeof(HAL_AENC_COM_CONFIG_S));

    // 从配置中读取参数
    std::string codec = audioConfig.value("codec", "aac");
    uint32_t sampleRate = audioConfig.value("sampleRate", 16000u);
    uint32_t bitWidth = audioConfig.value("bitWidth", 16u); // Assume kbps for now
    uint32_t channels = audioConfig.value("channel", 1u);

    // 映射 codec 字符串到 HAL_AUDIO_TYPE_E
    if (codec == "opus") {
        stAencConfig.eType = HAL_AUDIO_TYPE_OPUS;
    } else if (codec == "aac") {
        stAencConfig.eType = HAL_AUDIO_TYPE_AAC;
    } else if (codec == "g711a") {
        stAencConfig.eType = HAL_AUDIO_TYPE_G711_A;
    } else if (codec == "g711u") {
        stAencConfig.eType = HAL_AUDIO_TYPE_G711_U;
    } else {
        EL_ERROR("Unsupported audio codec: {}", codec);
        return false;
    }

    // 映射 sampleRate 到 HAL_AUDIO_SAMPLE_RATE_E
    if (sampleRate == 8000) {
        stAencConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_8000;
    } else if (sampleRate == 16000) {
        stAencConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_16000;
    } else if (sampleRate == 32000) {
        stAencConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_32000;
    } else if (sampleRate == 44100) {
        stAencConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_44100;
    } else if (sampleRate == 48000) {
        stAencConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_48000;
    } else {
        EL_WARN("Unsupported audio sample rate: {}, defaulting to 48000", sampleRate);
        stAencConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_48000;
    }

    if (bitWidth == 8) {
        stAencConfig.u32BitWidth = HAL_AUDIO_BIT_WIDTH_8;
    } else if (bitWidth == 16) {
        stAencConfig.u32BitWidth = HAL_AUDIO_BIT_WIDTH_16;
    } else if (bitWidth == 24) {
        stAencConfig.u32BitWidth = HAL_AUDIO_BIT_WIDTH_24;
    } else if (bitWidth == 32) {
        stAencConfig.u32BitWidth = HAL_AUDIO_BIT_WIDTH_32;
    } else {
        EL_WARN("Unsupported audio Bit Width: {}, defaulting to 16", bitWidth);
        stAencConfig.u32BitWidth = HAL_AUDIO_BIT_WIDTH_16;
    }

    // 设置其他参数 (bitWidth, channels)
    stAencConfig.u32SpkNum = channels; // 声道数
    stAencConfig.u8Vol = 100;          // 默认音量

    EL_INFO("Starting AENC ch:{} with codec:{}, sampleRate:{}, bitRate:{}, channels:{}", ch_, codec.c_str(), sampleRate,
            bitWidth, channels);

    int32_t ret = Hal_Aenc_Start(ch_, &stAencConfig);
    if (ret != HAL_SUCCESS) {
        EL_ERROR("Failed to start audio encoder ch:{}, ret=0x{:x}", ch_, ret);
        return false;
    }
    EL_INFO("Hal_Aenc_Start ch:{} success", ch_);
    return true;
}

void MediaAudioManager::StopAudio()
{
    int32_t ret = Hal_Aenc_Stop(ch_);
    if (ret != HAL_SUCCESS) {
        EL_ERROR("Failed to stop audio encoder ch:{}, ret=0x{:x}", ch_, ret);
        return;
    }
    EL_INFO("stop audio encoder ch:{} succeed", ch_);
}

void MediaAudioManager::Stop(int32_t handle)
{
    callbackManager_.Unregister(handle);
    // if (callbackManager_.IsEmpty()) {
    //     StopAudio();

    //     start_ = false;
    //     if (audioThread_) {
    //         audioThread_->join();
    //         audioThread_.reset();
    //     }
    // }

    EL_INFO("MediaAudioManager has stopped ch:{}", ch_);
}

void MediaAudioManager::AudioThread()
{
    prctl(PR_SET_NAME, "AudioMgrThd", 0, 0, 0);
    EL_INFO("Audio thread started for ch:{}", ch_);
    while (start_) {
        if (currentSource_ == AudioInputSource::BUILTIN) {
            // 从内置麦克风获取音频
            HAL_AENC_STREAM_S audioFrame;
            memset(&audioFrame, 0, sizeof(HAL_AENC_STREAM_S));
            int32_t ret = Hal_Aenc_GetStream(ch_, &audioFrame);
            if (ret != HAL_SUCCESS) {
                EL_ERROR("Failed to get audio stream ch:{}, ret=0x{:x}", ch_, ret);
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
                continue;
            }

            auto media = std::make_shared<MediaFrame>();
            if (!media->SetSize(audioFrame.u32DataLen)) {
                EL_DEBUG("Failed to set media frame size");
                Hal_Aenc_ReleaseStream(ch_, audioFrame.pRelHandler);
                continue;
            }
            media->PutBuffer(audioFrame.pData, audioFrame.u32DataLen);
            media->SetPts(audioFrame.u64TimeStamp);
            media->SetUtc(Utils::TimeManager::GetInstance().GetCurrentUtc());
            media->SetFrameType(MEDIA_FRAME_AAC);
            media->SetCodecType(MEDIA_AUDIO_CODEC_AAC);

            callbackManager_.InvokeAll(media);

            Hal_Aenc_ReleaseStream(ch_, audioFrame.pRelHandler);
        } else {
            // USB音频模式 - 数据通过UsbAudioEncoder的回调异步推送
            // 这里只需要保持线程活跃,实际数据处理在回调中完成
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    }
    EL_INFO("Audio thread is stopping ch:{}", ch_);
}

AudioInputSource MediaAudioManager::GetCurrentAudioSource() const
{
    return currentSource_;
}

} // namespace Media
} // namespace El
